﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using X3DXNA.core.CustomNodes;
using X3DXNA.interfaces;
using X3DXNA.core.Boundings;
using X3DXNA.services;
using X3DXNA.X3DSchema;
using X3DXNA.utils;

namespace X3DXNA.basicModels
{
    public class basicBoxModel : IGeometry
    {
        Game game;
        Model box;
        Matrix world;
        myBasicEffect basicEffect;
        MyBoundingBox modelBasicBoundingBox;
        Matrix basicTransformation;

        public Matrix getBasicTransformation { get { return basicTransformation; } }
        public Matrix World { get { return world; } set { world = value; } }
        public String DEF { get; set; }

        public basicBoxModel(String DEF, Game game, Vector3 size, Matrix initialTransformation)
        {
            this.DEF = DEF;
            this.game = game;
            this.world = initialTransformation;
            //Carico il modello.
            box = game.Content.Load<Model>("BasicModels/box");
            //Traggo il basicEffect dai servizi.
            this.basicEffect = (myBasicEffect)game.Services.GetService(typeof(myBasicEffect));
            //Calcolo la matrice di trasformazione dal "size" dell'X3D.
            this.basicTransformation = Matrix.CreateScale(size);
            //Applico la trasformazione del "size" alla trasformazione iniziale;
            world = basicTransformation * world;
            //Calcolo la boundingBox di base per questo modello...
            modelBasicBoundingBox = new MyBoundingBox(new BoundingBox(new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(0.5f, 0.5f, 0.5f)));
            //...e la trasformo, in base alla world definitiva.
            modelBasicBoundingBox.tranformBounding(world);
            box.Meshes[0].MeshParts[0].Effect = basicEffect.getBasicEffect;
            ((BasicEffect)box.Meshes[0].MeshParts[0].Effect).World = world;
        }

        public void draw()
        {
            box.Meshes[0].Draw();
        }

        /// <summary>
        /// Ritorna la boundig box per il modello. ATTENZIONE, se l'oggetto è dinamico, andrà ricalcolata ad ogni update.
        /// </summary>
        /// <returns>La IBounding per questo modello.</returns>
        public IBounding retrieveBounding()
        {
            return modelBasicBoundingBox;
        }

        public void applyWorldTransformation(Matrix transformation) { }

        public Vector3[] getTriangleVertices()
        {
            return (Vector3[])((Dictionary<string, object>)box.Tag)["Vertices"];
        }

        #region Public Static Builder

        public static basicBoxModel getNewBasicBoxModel(Game game, Box box, Matrix initialTransformation)
        {
            String DEF = "Default Box";
            Vector3 size = new Vector3(2, 2, 2);

            if (box.DEF != null)
                DEF = box.DEF;
            if (box.size != null)
                size = utility.stringToVector3(box.size);

            return new basicBoxModel(DEF, game, size, initialTransformation);
        }

        #endregion

    }
}
